package org.example.backend.service.impl;

import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import lombok.RequiredArgsConstructor;
import org.example.backend.model.Result;
import org.example.backend.model.WeatherAlert;
import org.example.backend.model.WeatherCurrent;
import org.example.backend.model.WeatherForecast;
import org.example.backend.service.WeatherService;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Service;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

/**
 * 天气服务实现类
 */
@Service
@RequiredArgsConstructor
public class WeatherServiceImpl implements WeatherService {

    private final WebClient weatherApiClient;
    private final Gson gson;

    @Override
    public Mono<Result<WeatherCurrent>> getCurrentWeather(String cityCode) {
        return weatherApiClient.get()
                .uri("/weather/current/{cityCode}", cityCode)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<WeatherCurrent>>() {});
    }

    @Override
    public Mono<Result<List<WeatherCurrent>>> getAllCurrentWeather() {
        return weatherApiClient.get()
                .uri("/weather/current")
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherCurrent>>>() {});
    }

    @Override
    public Mono<Result<List<WeatherForecast>>> getWeatherForecast(String cityCode) {
        return weatherApiClient.get()
                .uri("/weather/forecast/{cityCode}", cityCode)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherForecast>>>() {});
    }

    @Override
    public Mono<Result<List<WeatherAlert>>> getWeatherAlert(String cityCode) {
        return weatherApiClient.get()
                .uri("/weather/alert/{cityCode}", cityCode)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherAlert>>>() {});
    }

    @Override
    public Mono<Result<Map<String, Object>>> getAllWeatherInfo(String cityCode) {
        return weatherApiClient.get()
                .uri("/weather/all/{cityCode}", cityCode)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<Map<String, Object>>>() {});
    }

    @Override
    public Mono<Result<List<Map<String, Object>>>> getAllCities() {
        return weatherApiClient.get()
                .uri("/weather/cities")
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<Map<String, Object>>>>() {});
    }

    @Override
    public Mono<Result<List<WeatherCurrent>>> searchByName(String name) {
        return weatherApiClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/weather/search")
                        .queryParam("name", name)
                        .build())
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherCurrent>>>() {});
    }

    @Override
    public Mono<Result<Map<String, Object>>> getStatistics() {
        return weatherApiClient.get()
                .uri("/weather/statistics")
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<Map<String, Object>>>() {});
    }

    @Override
    public Mono<Result<List<WeatherCurrent>>> getHotCities() {
        return weatherApiClient.get()
                .uri("/weather/hot-cities")
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherCurrent>>>() {});
    }

    @Override
    public Mono<Result<List<WeatherCurrent>>> getColdCities() {
        return weatherApiClient.get()
                .uri("/weather/cold-cities")
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherCurrent>>>() {});
    }

    @Override
    public Mono<Result<List<WeatherCurrent>>> getCitiesByTemperatureRange(BigDecimal minTemp, BigDecimal maxTemp) {
        return weatherApiClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/weather/temperature-range")
                        .queryParam("minTemp", minTemp)
                        .queryParam("maxTemp", maxTemp)
                        .build())
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherCurrent>>>() {});
    }

    @Override
    public Mono<Result<WeatherForecast>> getForecastByDate(String cityCode, String date) {
        return weatherApiClient.get()
                .uri(uriBuilder -> uriBuilder
                        .path("/weather/forecast/date/{cityCode}")
                        .queryParam("date", date)
                        .build(cityCode))
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<WeatherForecast>>() {});
    }

    @Override
    public Mono<Result<List<WeatherCurrent>>> getCitiesByWeatherCondition(String condition) {
        return weatherApiClient.get()
                .uri("/weather/weather-condition/{condition}", condition)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<List<WeatherCurrent>>>() {});
    }

    @Override
    public Mono<Result<Map<String, List<WeatherCurrent>>>> compareCities(List<String> cityCodes) {
        return weatherApiClient.post()
                .uri("/weather/compare")
                .bodyValue(cityCodes)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Result<Map<String, List<WeatherCurrent>>>>() {});
    }
} 